<template>
  <button
    :style="buttonStyle"
    :class="classNames"
    hover-class="none"
    :disabled="mergedDisabled"
    @click="handleClick"
  >
    <text class="arco-switch-handle">
      <text class="arco-switch-handle-icon">
        <slot v-if="computedCheck" name="checked-icon"> </slot>
        <slot v-else name="unchecked-icon"> </slot>
        <aIcon v-if="computedLoading" name="loading" spin />
      </text>
    </text>
    <template
      v-if="
        type !== 'line' && size !== 'small' && (checkedText || uncheckedText)
      "
    >
      <text class="arco-switch-text-holder">
        <slot v-if="computedCheck" name="checked">{{ checkedText }}</slot>
        <slot v-else name="unchecked">{{ uncheckedText }}</slot>
      </text>
      <text class="arco-switch-text">
        <slot v-if="computedCheck" name="checked">
          {{ checkedText }}
        </slot>
        <slot v-else name="unchecked"> {{ uncheckedText }}</slot>
      </text>
    </template>
  </button>
</template>

<script lang="ts">
import { useFormItem } from "@/ArcoUni/hook/use-form-item";
import { useSize } from "@/ArcoUni/hook/use-size";
import { isFunction } from "@/utils/is";
import { computed, defineComponent, ref, toRefs } from "vue";
import aIcon from "../arco-icon/index.vue";
const Switch = defineComponent({
  name: "SwitcH",
  options: {
    // 虚拟化节点
    virtualHost: true,
  },
  components: {
    aIcon,
  },
  props: {
    modelValue: {
      type: [String, Number, Boolean],
      default: void 0,
    },
    defaultChecked: {
      type: Boolean,
      default: false,
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    loading: {
      type: Boolean,
      default: false,
    },
    type: {
      type: String,
      default: "circle",
    },
    size: {
      type: String,
    },
    checkedValue: {
      type: [String, Number, Boolean],
      default: true,
    },
    uncheckedValue: {
      type: [String, Number, Boolean],
      default: false,
    },
    checkedColor: {
      type: String,
    },
    uncheckedColor: {
      type: String,
    },
    beforeChange: {
      type: Function,
    },
    checkedText: {
      type: String,
    },
    uncheckedText: {
      type: String,
    },
  },
  emits: ["update:modelValue", "change", "focus", "blur"],
  setup(props, { slots, emit }) {
    const { disabled, size } = toRefs(props);
    const prefixCls = "arco-switch";
    const visible = ref(true);

    const { mergedSize: configSize } = useSize(size);
    // eventHandlers
    const { mergedDisabled, mergedSize, eventHandlers } = useFormItem({
      disabled,
      size: configSize,
    });

    const _loading = ref(props.loading);

    const _checked = ref(
      props.defaultChecked ? props.checkedValue : props.uncheckedValue,
    );

    const computedCheck = computed(() => {
      var _a;
      return (
        ((_a = props.modelValue) != null ? _a : _checked.value) ===
        props.checkedValue
      );
    });

    const computedLoading = computed(() => _loading.value || props.loading);

    const handleClick = async (ev) => {
      if (computedLoading.value || mergedDisabled.value) {
        return;
      }
      const checked = !computedCheck.value;
      const checkedValue = checked ? props.checkedValue : props.uncheckedValue;
      const shouldChange = props.beforeChange;
      if (isFunction(shouldChange)) {
        _loading.value = true;
        try {
          const result = await shouldChange(checkedValue);
          if (result != null ? result : true) {
            handleChange(checked, ev);
          }
        } finally {
          _loading.value = false;
        }
      } else {
        handleChange(checked, ev);
      }
    };

    const handleChange = (checked, ev) => {
      var _a, _b;
      _checked.value = checked ? props.checkedValue : props.uncheckedValue;
      emit("update:modelValue", _checked.value);
      emit("change", _checked.value);
      // eslint-disable-next-line @typescript-eslint/no-unused-expressions
      (_b = (_a = eventHandlers.value) == null ? void 0 : _a.onChange) == null
        ? void 0
        : _b.call(_a, ev);
    };

    const isaction = computed(() => {
      return Boolean(slots.action);
    });

    const classNames = computed(() => {
      return [
        prefixCls,
        `${prefixCls}-type-${props.type}`,
        {
          [`${prefixCls}-small`]:
            mergedSize.value === "small" || mergedSize.value === "mini",
          [`${prefixCls}-checked`]: computedCheck.value,
          [`${prefixCls}-disabled`]: mergedDisabled.value,
          [`${prefixCls}-loading`]: computedLoading.value,
          [`${prefixCls}-custom-color`]:
            props.type === "line" &&
            (props.checkedColor || props.uncheckedColor),
        },
      ];
    });

    const buttonStyle = computed(() => {
      if (computedCheck.value && props.checkedColor) {
        return props.type === "line"
          ? { "--custom-color": props.checkedColor }
          : { backgroundColor: props.checkedColor };
      }
      if (!computedCheck.value && props.uncheckedColor) {
        return props.type === "line"
          ? { "--custom-color": props.uncheckedColor }
          : { backgroundColor: props.uncheckedColor };
      }
      return void 0;
    });

    return {
      prefixCls,
      classNames,
      visible,
      isaction,
      mergedDisabled,
      computedLoading,
      buttonStyle,
      handleClick,
      computedCheck,
    };
  },
});
export default Switch;
</script>
